package cloud.lysky.java.on.concurrent.threadpool;

import java.sql.Connection;
import java.util.LinkedList;

/**
 * @author luoly
 * @describe
 * @date 2023/3/2 17:35
 **/
/* 使用线程间wait notify协同机制实现简单数据库连接池 */
public class ThreadPoolWaitAndNotifyImpl {

    /* 容器，存放数据库连接 */
    private static final LinkedList<Connection> pool = new LinkedList<>();

    public ThreadPoolWaitAndNotifyImpl(int initialSize){
        if (initialSize > 0){
            for (int i = 0; i < initialSize; i++) {
                pool.addLast(SqlConnectionImpl.fetchConnection());
            }
        }
    }

    /* 释放连接，通知其它的等待连接的线程 */
    public void releaseConnection(Connection connection){
        if (connection != null) {
            synchronized (pool){
                pool.addLast(connection);
                /* 通知其它等待连接的线程 */
                pool.notifyAll();
            }
        }
    }

    /* 获取连接 */
    //在mills内无法获取到连接将返回null
    public Connection fetchConnection(long mills) throws InterruptedException {
        synchronized (pool){
            if (mills < 0) {
                //用不超时，无期限等待
                while (pool.isEmpty()){
                    System.out.println("连接池里没有可用的连接,线程["+ Thread.currentThread().getName() + "]开始等待");
                    pool.wait();
                }
                System.out.println("线程池里有空闲的连接，线程["+ Thread.currentThread().getName() + "]获取一个连接");
                return pool.removeFirst();
            } else{
                /* 超时时间 */
                long future = System.currentTimeMillis() + mills;
                /* 等待时长 */
                long remaining = mills;
                while (pool.isEmpty() && remaining > 0){
                    System.out.println("连接池里没有可用的连接,线程["+ Thread.currentThread().getName() + "]开始等待");
                    pool.wait(remaining);
                    /* 唤醒一次 重新计算等待时长 */
                    remaining = future - System.currentTimeMillis();
                }
                Connection connection = null;
                if (!pool.isEmpty()){
                    System.out.println("线程池里有空闲的连接，线程["+ Thread.currentThread().getName() + "]获取一个连接");
                    connection = pool.removeFirst();
                }
                return connection;
            }
        }
    }
}
